﻿using Abp;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using AutoMapper.QueryableExtensions;
using FwProject.Core.Restaurant;
using FwProject.Core.SettlementInfoModel;
using FwProject.PrePaymentInfo.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using X.PagedList;

namespace FwProject.PrePaymentInfo
{
    /// <summary>
    /// 预收款管理
    /// </summary>
    [AbpAuthorize]
    public class PrePaymentInfoAppService : FwProjectAppServiceBase, IPrePaymentInfoAppService
    {
        public readonly IRepository<PrePaymentInfoModel, Guid> _repositoryPrePaymentInfoModel;
        public readonly IRepository<SettlementAccount, Guid> _repositorySettlementAccount;
        public readonly IRepository<RestaurantUserInfo, Guid> _repositoryRestaurantUserInfo;
        public readonly IRepository<RestaurantInfo, Guid> _repositoryRestaurantInfo;
        public readonly IRepository<ReceiptInfoModel, Guid> _repositoryReceiptInfoModel;
        public IGuidGenerator _guid { get; set; }


        public PrePaymentInfoAppService(IRepository<PrePaymentInfoModel, Guid> repositoryPrePaymentInfoModel,
            IRepository<SettlementAccount, Guid> repositorySettlementAccount,
            IRepository<RestaurantUserInfo, Guid> repositoryRestaurantUserInfo,
            IRepository<RestaurantInfo, Guid> repositoryRestaurantInfo,
            IRepository<ReceiptInfoModel, Guid> repositoryReceiptInfoModel)
        {
            _repositoryPrePaymentInfoModel = repositoryPrePaymentInfoModel;
            _repositorySettlementAccount = repositorySettlementAccount;
            _repositoryRestaurantUserInfo = repositoryRestaurantUserInfo;
            _repositoryRestaurantInfo = repositoryRestaurantInfo;
            _repositoryReceiptInfoModel = repositoryReceiptInfoModel;
            _guid = SequentialGuidGenerator.Instance;
        }


        public async Task<IPagedList<PrePaymentInfoOutputDto>> GetPagedListAsync(int pageIdx, int pageSize, PrePaymentInfoType type, string keyword, PrePaymentInfoStatus? PrePaymentInfoStatus)
        {
            var user = await base.GetCurrentUserAsync();
            //当前登录人所属工厂下的餐厅
            var query = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.PrePaymentInfoType == type && o.FactoryinfoId == user.FactoryinfoId);
            if (!string.IsNullOrEmpty(keyword))
                query = query.Where(o => o.PrePaymentInfoNumber.Contains(keyword));
            if (PrePaymentInfoStatus.HasValue)
                query = query.Where(o => o.PrePaymentInfoStatus== PrePaymentInfoStatus);

            return await query.OrderByDescending(m => m.CreationTime).ProjectTo<PrePaymentInfoOutputDto>().ToPagedListAsync(pageIdx, pageSize);
        }

        public async Task<List<PrePaymentInfoOutputDto>> GetAllListAsync(PrePaymentInfoType type, string keyword)
        {
            var user = await base.GetCurrentUserAsync();
            //当前登录人所属工厂下的餐厅
            var query = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.PrePaymentInfoType == type && o.FactoryinfoId == user.FactoryinfoId);
            if (!string.IsNullOrEmpty(keyword))
                query = query.Where(o => o.PrePaymentInfoNumber.Contains(keyword));

            return await query.OrderByDescending(m => m.CreationTime).ProjectTo<PrePaymentInfoOutputDto>().ToListAsync();
        }

        public async Task<PrePaymentInfoEnterDto> GetEnterDto(Guid id)
        {
            var entity = await _repositoryPrePaymentInfoModel.GetAsync(id);
            return entity.MapTo<PrePaymentInfoEnterDto>();
        }
        /// <summary>
        /// 根据餐厅获取预收金
        /// </summary>
        /// <param name="restaurantId"></param>
        /// <returns></returns>
        public async Task<List<PrePaymentInfoEnterDto>> GetListByRestaurantIdAsync(Guid restaurantId)
        {
            var model = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.RestaurantInfoId == restaurantId && o.PrePaymentInfoType==PrePaymentInfoType.退预交金);
            return await model.ProjectTo<PrePaymentInfoEnterDto>().ToListAsync();
        }

        /// <summary>
        /// 获取预收款单打印数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<PrePaymentPrintDto> GetPrePaymentPrintModelAsync(Guid id)
        {
            var model = await _repositoryPrePaymentInfoModel.GetAsync(id);
            return model.MapTo<PrePaymentPrintDto>();
        }
        /// <summary>
        /// 获取一个预收款信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<PrePaymentInfoOutputDto> GetEntityAsync(Guid id)
        {
            var entity = await _repositoryPrePaymentInfoModel.GetAsync(id);
            return entity.MapTo<PrePaymentInfoOutputDto>();
        }
        /// <summary>
        /// 创建一个餐厅预收款信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Guid> CreateAsync(PrePaymentInfoEnterDto input)
        {
            var model = input.MapTo<PrePaymentInfoModel>();
            var account = await _repositorySettlementAccount.GetAsync(input.CapitalAccountId);
            model.AccountNo = account.Number;
            model.AccountName = account.Name;

            model.Id = _guid.Create();
            if (input.PrePaymentInfoType == PrePaymentInfoType.退预交金)
            {
                var list = await _repositoryPrePaymentInfoModel.GetAll().Where(o => o.RestaurantInfoId == input.RestaurantInfoId && o.PrePaymentInfoStatus == PrePaymentInfoStatus.已审核).ToListAsync();
                //已预交金额
                var already = list.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.收预交金).Sum(o => o.PrePaymentPrice);
                //已退金额
                var retired = list.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.退预交金).Sum(o => o.PrePaymentPrice);

                model.PreviousPrice = already - retired;
            }
            model.FactoryinfoId = (await GetCurrentUserAsync()).FactoryinfoId.Value;
            return await _repositoryPrePaymentInfoModel.InsertAndGetIdAsync(model);
        }
        /// <summary>
        /// 手改一条预收款信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task ModifyAsync(Guid id, PrePaymentInfoEnterDto input)
        {
            var model = await _repositoryPrePaymentInfoModel.GetAsync(id);
            input.MapTo(model);
            if (input.PrePaymentInfoStatus != PrePaymentInfoStatus.已审核)
            {
                var original = model.CapitalAccountId;
                var originalPrice = model.PrePaymentPrice;
                if (original != model.CapitalAccountId)
                {
                    var account = await _repositorySettlementAccount.GetAsync(model.CapitalAccountId);
                    model.AccountNo = account.Number;
                    model.AccountName = account.Name;
                }

                if (input.PrePaymentInfoType == PrePaymentInfoType.退预交金 && originalPrice != input.PrePaymentPrice)
                {
                    var list = await _repositoryPrePaymentInfoModel.GetAll().Where(o => o.RestaurantInfoId == input.RestaurantInfoId && o.PrePaymentInfoStatus == PrePaymentInfoStatus.已审核).ToListAsync();
                    //已预交金额
                    var already = list.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.收预交金).Sum(o => o.PrePaymentPrice);
                    //已退金额
                    var retired = list.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.退预交金).Sum(o => o.PrePaymentPrice);

                    model.PreviousPrice = already - retired;
                }

                await _repositoryPrePaymentInfoModel.UpdateAsync(model);
            }
            //if (model.PrePaymentInfoStatus == PrePaymentInfoStatus.已审核)
            //{
            //input.MapTo(model);
            await _repositoryPrePaymentInfoModel.UpdateAsync(model);
           // }
        }

        public async Task DeleteAsync(Guid id)
        {
            await _repositoryPrePaymentInfoModel.DeleteAsync(id);
        }
        #region  获取餐厅预收款金额
        /// <summary>
        /// 获取餐厅预收款金额
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<decimal> GetPaymentOverAsync(Guid id)
        {
            var user = await base.GetCurrentUserAsync();
            var list = await _repositoryPrePaymentInfoModel.GetAll().Where(o => o.RestaurantInfoId == id && o.PrePaymentInfoStatus == PrePaymentInfoStatus.已审核 && o.FactoryinfoId == user.FactoryinfoId).ToListAsync();
            //已预交金额
            var already = list.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.收预交金).Sum(o => o.PrePaymentPrice);
            //已退金额
            var retired = list.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.退预交金).Sum(o => o.PrePaymentPrice);
            return already - retired;
        }
        #endregion
        #region  预收款余额列表
        public async Task<IPagedList<AdvanceOverageOutputDto>> GetAdvanceOveragePagedListAsync(int pageIdx, int pageSize, bool isnull, string keyword)
        {
            var user = await base.GetCurrentUserAsync();

            var query = _repositoryRestaurantInfo.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId).GroupJoin(_repositoryPrePaymentInfoModel.GetAll().Where(o => o.PrePaymentInfoStatus == PrePaymentInfoStatus.已审核 && o.FactoryinfoId == user.FactoryinfoId), i => i.Id, j => j.RestaurantInfoId, (i, j) => new
            {
                i.Id,
                i.RestaurantName,
                i.RestaurantContact,
                i.Mobile,
                Overage = j.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.收预交金).Sum(o => o.PrePaymentPrice) - j.Where(o => o.PrePaymentInfoType == PrePaymentInfoType.退预交金).Sum(o => o.PrePaymentPrice),
            }).GroupJoin(_repositoryReceiptInfoModel.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId && o.ToVoid==ToVoidStatus.未作废).GroupBy(s => s.RestaurantId).Select(s => new { RestaurantId = s.Key, UsePrePayment = s.Sum(o => o.UsePrePayment) })
            , i => i.Id, j => j.RestaurantId, (i, j) => new
            {
                i.Id,
                i.RestaurantName,
                i.RestaurantContact,
                i.Mobile,
                Overage = i.Overage - j.Sum(s => s.UsePrePayment)
            }
            );

            if (!isnull)
                query = query.Where(o => o.Overage != 0m);

            if (!string.IsNullOrEmpty(keyword))
                query = query.Where(o => o.RestaurantName.Contains(keyword));

            var pagelist = await query.Select(i => new AdvanceOverageOutputDto
            {
                RestaurantInfoName = i.RestaurantName,
                Overage = i.Overage,
                Mobile = i.RestaurantContact,
                Principal = i.Mobile,
            }).ToPagedListAsync(pageIdx, pageSize);

            return pagelist;
        }
        #endregion
        #region App查看餐厅的预收金额
        /// <summary>
        /// 根据餐厅编号返回该餐厅的预收金额
        /// </summary>
        /// <param name="RestaurantId"></param>
        /// <returns></returns>
        public async Task<decimal> GetRestaurantInfoNamePrePayment(Guid RestaurantId)
        {
            var user = await base.GetCurrentUserAsync();
            var sk = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId && o.RestaurantInfoId == RestaurantId && o.PrePaymentInfoType == PrePaymentInfoType.收预交金).Sum(s => s.PrePaymentPrice);
            var tk = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId && o.RestaurantInfoId == RestaurantId && o.PrePaymentInfoType == PrePaymentInfoType.退预交金).Sum(s => s.PrePaymentPrice);
            var receipt = _repositoryReceiptInfoModel.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId && o.RestaurantId == RestaurantId && o.ToVoid==ToVoidStatus.未作废).Sum(o => o.UsePrePayment);
            return sk - tk - receipt <= 0 ? 0 : sk - tk - receipt;
        }
        /// <summary>
        /// 修改收款是判断预收款
        /// </summary>
        /// <param name="RestaurantId"></param>
        /// <returns></returns>
        public async Task<decimal> GetRestaurantInfoByReceiptInfoIdPayment(Guid RestaurantId,Guid receiptInfoId)
        {
            var user = await base.GetCurrentUserAsync();
            var sk = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId && o.RestaurantInfoId == RestaurantId && o.PrePaymentInfoType == PrePaymentInfoType.收预交金).Sum(s => s.PrePaymentPrice);
            var tk = _repositoryPrePaymentInfoModel.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId && o.RestaurantInfoId == RestaurantId && o.PrePaymentInfoType == PrePaymentInfoType.退预交金).Sum(s => s.PrePaymentPrice);
            var receipt = _repositoryReceiptInfoModel.GetAll().Where(o => o.FactoryinfoId == user.FactoryinfoId && o.RestaurantId == RestaurantId && o.Id!= receiptInfoId && o.ToVoid == ToVoidStatus.未作废).Sum(o => o.UsePrePayment);
            return sk - tk - receipt <= 0 ? 0 : sk - tk - receipt;
        }

        #endregion

    }
}
